from typing import TypedDict

class PTYMetaDict(TypedDict):
    id: str
    name: str
    command: str
    closed: bool

import json
from enum import Enum
from dataclasses import dataclass
from typing import Any, Union, List, TYPE_CHECKING
# from py_ts_interfaces import Interface

import json
import logging
from typing import Any
# from MelodieInfra import DataServiceStatus
logger = logging.getLogger(__file__)


class Response:
    OK = 0
    ERROR = 1

    @staticmethod
    def _create_response(status: int, message: str, data: Any) -> str:
        assert status in {Response.OK, Response.ERROR}
        try:
            resp = json.dumps({"status": status, "msg": message, "data": data})
            if status == Response.ERROR:
                logger.info(resp)
            return resp
        except TypeError:
            import traceback

            traceback.print_exc()
            logger.error(str(data))
            return 'Internal error occurred in MelodieStudio'

    @staticmethod
    def ok(data: Any) -> str:
        return Response._create_response(Response.OK, "", data)

    @staticmethod
    def success_msg(msg: str) -> str:
        return Response._create_response(Response.OK, msg, {})

    @staticmethod
    def error(msg: str) -> str:
        return Response._create_response(Response.ERROR, msg, None)

    @staticmethod
    def resp_json_from_data_service_status(ds_status: "DataServiceStatus"):
        return ds_status.to_json()
class WSMessageTypes(str, Enum):
    SUBPROCESS_OUTPUT = "subprocess-output"
    PLOT = "plot"
    MESSAGE = "message"
    PTY_OUTPUT = "pty-output"
    FS_EVENT = "fs-event"
    PTY_STATUS_CHANGE = "pty-status-change"


if TYPE_CHECKING:
    import typing

    class WSMessageDict(typing.TypedDict):
        type: WSMessageTypes
        payload: Any


@dataclass
class WSMessage:
    type: WSMessageTypes
    payload: Union[Any, List]

    def __post_init__(self) -> None:
        assert self.type in WSMessageTypes

    def dump(self) -> str:
        return json.dumps(self.to_dict())

    def to_dict(self) -> "WSMessageDict":
        return {"type": self.type, "payload": self.payload}


@dataclass
class WSToServerMessage:
    type: WSMessageTypes
    payload: Any

    def __post_init__(self) -> None:
        assert self.type in {"command"}

    def dump(self) -> str:
        return json.dumps(self.to_dict())

    def to_dict(self) -> "WSMessageDict":
        return {"type": self.type, "payload": self.payload}